<script>
    import ajax from './ajax';
    import UploadDragger from './upload-dragger.vue';

    export default {
        inject: ['uploader'],
        components: {
            UploadDragger
        },
        props: {
            type: String,
            action: {
                type: String,
                required: true
            },
            name: {
                type: String,
                default: 'file'
            },
            data: Object,
            headers: Object,
            withCredentials: Boolean,
            multiple: Boolean,
            accept: String,
            onStart: Function,
            onProgress: Function,
            onSuccess: Function,
            onError: Function,
            beforeUpload: Function,
            drag: Boolean,
            onPreview: {
                type: Function,
                default: function () {
                }
            },
            onRemove: {
                type: Function,
                default: function () {
                }
            },
            fileList: Array,
            autoUpload: Boolean,
            listType: String,
            httpRequest: {
                type: Function,
                default: ajax
            },
            disabled: Boolean,
            limit: Number,
            onExceed: Function
        },

        data() {
            return {
                mouseover: false,
                reqs: {}
            };
        },

        methods: {
            isImage(str) {
                return str.indexOf('image') !== -1;
            },
            handleChange(ev) {
                const files = ev.target.files;

                if (!files) return;
                this.uploadFiles(files);
            },
            uploadFiles(files) {
                if (this.limit && this.fileList.length + files.length > this.limit) {
                    this.onExceed && this.onExceed(files, this.fileList);
                    return;
                }

                let postFiles = Array.prototype.slice.call(files);
                if (!this.multiple) {
                    postFiles = postFiles.slice(0, 1);
                }

                if (postFiles.length === 0) {
                    return;
                }

                postFiles.forEach(rawFile => {
                    this.onStart(rawFile);
                    if (this.autoUpload) this.upload(rawFile);
                });
            },
            upload(rawFile) {
                this.$refs.input.value = null;

                if (!this.beforeUpload) {
                    return this.post(rawFile);
                }

                const before = this.beforeUpload(rawFile);
                if (before && before.then) {
                    before.then(processedFile => {
                        const fileType = Object.prototype.toString.call(processedFile);

                        if (fileType === '[object File]' || fileType === '[object Blob]') {
                            if (fileType === '[object Blob]') {
                                processedFile = new File([processedFile], rawFile.name, {
                                    type: rawFile.type
                                });
                            }
                            for (const p in rawFile) {
                                if (rawFile.hasOwnProperty(p)) {
                                    processedFile[p] = rawFile[p];
                                }
                            }
                            this.post(processedFile);
                        } else {
                            this.post(rawFile);
                        }
                    }, () => {
                        this.onRemove(null, rawFile);
                    });
                } else if (before !== false) {
                    this.post(rawFile);
                } else {
                    this.onRemove(null, rawFile);
                }
            },
            abort(file) {
                const {reqs} = this;
                if (file) {
                    let uid = file;
                    if (file.uid) uid = file.uid;
                    if (reqs[uid]) {
                        reqs[uid].abort();
                    }
                } else {
                    Object.keys(reqs).forEach((uid) => {
                        if (reqs[uid]) reqs[uid].abort();
                        delete reqs[uid];
                    });
                }
            },
            post(rawFile) {
                const {uid} = rawFile;
                const options = {
                    headers: this.headers,
                    withCredentials: this.withCredentials,
                    file: rawFile,
                    data: this.data,
                    filename: this.name,
                    action: this.action,
                    onProgress: e => {
                        this.onProgress(e, rawFile);
                    },
                    onSuccess: res => {
                        this.onSuccess(res, rawFile);
                        delete this.reqs[uid];
                    },
                    onError: err => {
                        this.onError(err, rawFile);
                        delete this.reqs[uid];
                    }
                };
                const req = this.httpRequest(options);
                this.reqs[uid] = req;
                if (req && req.then) {
                    req.then(options.onSuccess, options.onError);
                }
            },
            handleClick() {
                if (!this.disabled) {
                    this.$refs.input.value = null;
                    this.$refs.input.click();
                }
            },
            handleKeydown(e) {
                if (e.target !== e.currentTarget) return;
                if (e.keyCode === 13 || e.keyCode === 32) {
                    this.handleClick();
                }
            }
        },

        render(h) {
            let {
                handleClick,
                drag,
                name,
                handleChange,
                multiple,
                accept,
                listType,
                uploadFiles,
                disabled,
                handleKeydown
            } = this;
            const data = {
                class: {
                    'el-upload': true
                },
                on: {
                    click: handleClick,
                    keydown: handleKeydown
                }
            };
            data.class[`el-upload--${listType}`] = true;
            return (
                < div
            {...
                data
            }
            tabindex = "0" >
                {
                    drag
                            ? < upload - dragger
            disabled = {disabled}
            on - file = {uploadFiles} > {this.$slots.default
        }<
            /upload-dragger>
        :
            this.$slots.default
        }
        <
            input
        class
            = "el-upload__input"
            type = "file"
            ref = "input"
            name = {name}
            on - change = {handleChange}
            multiple = {multiple}
            accept = {accept} > < /input>
                < /div>
        )
            ;
        }
    };
</script>
